/**
 * @file	hal_uart.c
 * @author	chensj0621
 * @brief	
 * @version	0.1
 * @date	2021-11-11
 * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
 * @note
 */

/*********************************************************************
 * INCLUDES
 */
#include "hal_uart.h"

/********************变量定义区****************************/
uint8_t Hal_UartTaskID;

hal_uart_t hal_uart;
hal_uart_data_t user_data;
uint32_t uart_prev_time = 0;
uint32_t uart_curr_time = 0;
/**
 * @brief bank_curr_num
 * 
 */
uint8_t bank_curr_num = 0;
uint8_t uart_check_sum = 0;

uint8_t uart_send_buff[UART_BUF_SIZE];

const uint32_t baud_table[5] = {115200, 57600, 38400, 19200, 9600};
//100ms,200ms,300,ms,400ms,500ms,1000ms,2000ms,3000ms,4000ms
const uint16_t advin_table[9] = {160, 320, 480, 640, 800, 1600, 3200, 4800, 6400};
//50ms,100ms,200,ms,300ms,500ms,1000ms,1500ms
const uint16_t connin_table[7] = {40, 80, 160, 240, 400, 800, 1200};

const uint8_t power_table[5] = {0x06, 0x0a, 0x0d, 0x1d, 0x1d};
//10ms,20ms,30,ms,40ms,50ms
const uint8_t scan_window_table[5] = {10, 20, 30, 40, 50};
//0ms,100ms,200ms,300ms,400ms,500ms,1000ms,2000ms,3000ms,4000ms,
const uint32_t scan_interval_table[10] = {0, 100, 200, 300, 400,500,1000,2000,3000,4000};


//按键唤醒回调
void wakeup_pin_hdl(GpioPin_t pin,gpio_polarity_e type)
{
    if(pin == WAKEUP_PIN)
    {
        osal_stop_timerEx(Hal_UartTaskID, USR_WAKEUP_PIN_DET);
        osal_start_timerEx(Hal_UartTaskID, USR_WAKEUP_PIN_DET, PIN_DEBONCE_TIME);
    }
}


/**
 * @fn      void HalPeripheral_Init(uint8 task_id)
 * @brief   Peripheral initialization
 * @param   task_id
 * @return  none
 */
void __ATTR_SECTION_SRAM__ uart_receive_callback(uart_Evt_t* pev)//串口收数据回调
{
    switch(pev->type)
    {
        case UART_EVT_TYPE_RX_DATA:
        case UART_EVT_TYPE_RX_DATA_TO:
           
            if(hal_uart.rx_idx < UART_RX_BUFF_MAX)
            {
                osal_memcpy(hal_uart.rx_data+hal_uart.rx_idx, pev->data, pev->len);
                hal_uart.rx_idx = hal_uart.rx_idx + pev->len;
                //LOG("-%02x-%02x\n",hal_uart.rx_data[hal_uart.rx_idx-1],hal_uart.rx_data[hal_uart.rx_idx-2]);

                uart_prev_time = (TIME_BASE - ((AP_TIM3->CurrentCount) >> 2));
                //LOG("time %d %d %d\n",TIME_DELTA(uart_curr_time, uart_prev_time),uart_curr_time,);
                if(uart_prev_time != uart_curr_time)
                {
                    
                    if(TIME_DELTA(uart_curr_time, uart_prev_time) > UART_REC_TIMEOUT)
                    {
                        osal_start_timerEx(Hal_UartTaskID, USR_UART_AT_DATA, 50);
                    }
                    uart_curr_time = uart_prev_time;
                }

                //if((hal_uart.rx_data[hal_uart.rx_idx-1]=='\n')&&(hal_uart.rx_data[hal_uart.rx_idx-2]=='\r'))
                {
                    //osal_start_timerEx(Hal_UartTaskID, USR_UART_AT_DATA, NULL);
                }
            }
            else
            {
                hal_uart.rx_idx = 0;
            }
            
            //for(int i = 0 ; i < hal_uart.rx_idx ; i++)
            //{
            //    LOG("data [%d] = %c\n ",i,hal_uart.rx_data[i]);
            //}
            

        break;
        
        case UART_EVT_TYPE_TX_COMPLETED:

            //osal_stop_timerEx(Hal_UartTaskID, USR_UART_SEND_DATA);
            //osal_set_event(Hal_UartTaskID, USR_UART_SEND_DATA);
        break;
    }
}

void uart_send_process(void)
{
    //HalUartSendBuf(UART1, uart_send_buff, 20);
}

uint16 HalPeripheral_ProcessEvent( uint8 task_id, uint16 events )
{
    //uint8_t temp_index;
    

    //LOG("task_id %d events %d\n",task_id,events);
    if(task_id != Hal_UartTaskID)
    {
        return 0;
    }

    if( events & USR_UART_AT_DATA )
    {
        attMsg_t sendMsg;
        //uint8_t channel;
        uint8_t temp_mode = ble_get_at_mode();
        osal_memcpy(sendMsg.writeReq.value, hal_uart.rx_data, hal_uart.rx_idx);
        sendMsg.writeReq.len = hal_uart.rx_idx;
        //for(int i = 0 ; i < hal_uart.rx_idx ; i++)
        {
          //  LOG("data [%d] = %c\n ",i,hal_uart.rx_data[i]);
        }
        if(osal_memcmp(hal_uart.rx_data, "AT\r\n", 4))//测试命令单独出来
        {
            //LOG("at_test %d\n",hal_uart.rx_idx);
            HalUartSendBuf(UART1, "OK\r\n", 4);
            at_data.at_cmd_flag = 1;
        }
        else if(osal_memcmp(hal_uart.rx_data, "OK\r\n", 4))//回复信号单独出来
        {
            LOG("OK !\n");
            ble_set_ok_flag(TRUE);
        }
        else if(osal_memcmp(hal_uart.rx_data, "AT", 2))
        {
            LOG("uart <<== len  %d\n",hal_uart.rx_idx);
            at_command_process(hal_uart.rx_data,hal_uart.rx_idx, AT_UART);

        }
        if(at_data.at_cmd_flag == 0)
        {
            if(hal_uart.rx_idx < 247)//超过247无事发生
            {
                osal_memcpy(sendMsg.writeReq.value, hal_uart.rx_data, hal_uart.rx_idx);//这里要未来要作长度判断处理，用来控制串口每次数据长度
                sendMsg.writeReq.len = hal_uart.rx_idx;
                if(temp_mode == BLE_MASTER_AND_SLAVE)
                {
                    if(at_data.ble_send_role == AT_MASTER)
                    {
                        LOG("MASTER\n");
                        user_data_send_by_ble(LL_ROLE_SLAVE,at_data.ble_send_index,&sendMsg);
                    }
                    else if(at_data.ble_send_role == AT_SLAVE)
                    {
                        
                        uint8_t ret = user_data_send_by_ble(LL_ROLE_MASTER,at_data.ble_send_index,&sendMsg);
                        LOG("slave ret \n",ret);
                    }
                }
                else if(temp_mode == BLE_ONLY_MASTER)
                {
                    LOG("BLE_ONLY_MASTER slave\n");
                    user_data_send_by_ble(LL_ROLE_MASTER,at_data.ble_send_index,&sendMsg);
                }
                else if(temp_mode == BLE_ONLY_SLAVE)
                {
                    user_data_send_by_ble(LL_ROLE_SLAVE,0,&sendMsg);
                }

            }

        }
        else
        {
            at_data.at_cmd_flag = 0;
        }
        osal_memset(&hal_uart, 0, sizeof(hal_uart));
        return ( events ^ USR_UART_AT_DATA );
    }
    
   if( events & USR_WAKEUP_PIN_DET )
    {
        static uint8_t det_times = 0;
        
        if( HalGpioGet(WAKEUP_PIN) )
        {
            det_times++;
            if(det_times > 3)
            {
                det_times = 0;
                LOG("sleep\r\n");
                hal_pwrmgr_unlock(MOD_GPIO);
            }
            else
            {
                osal_stop_timerEx(Hal_UartTaskID, USR_WAKEUP_PIN_DET);
                osal_start_timerEx(Hal_UartTaskID, USR_WAKEUP_PIN_DET, PIN_DEBONCE_TIME);
            }
        }
        else
        {
            //LOG("wakeup\r\n");
            det_times = 0;
            hal_pwrmgr_lock(MOD_GPIO);
            osal_stop_timerEx(Hal_UartTaskID, USR_WAKEUP_PIN_DET);
            osal_start_timerEx(Hal_UartTaskID, USR_WAKEUP_PIN_DET, PIN_DETECTION_TIME);
        }
        
        return ( events ^ USR_WAKEUP_PIN_DET );
    }

    if( events & USR_UART_SEND_DATA )
    {
        //uart_send_process();

        return ( events ^ USR_UART_SEND_DATA );
    }
    
    if( events & USR_EVT_OTHER)
    {
        return ( events ^ USR_EVT_OTHER );
    }
    
    // Discard unknown events
    return 0;

}

uint8 user_data_sum(uint16 len, uint8 *data)
{
    uint8 ret = 0;
    for(uint16 i=0; i<len; i++)
    {
        ret += data[i];
    }
    //ret -= user_data.check_sum;//减去校验码
    return ret;
}
void user_at_init(void)
{
    LL_WriteBDADDR(user_data.mac);
    osal_set_event(gapRole_TaskID, START_CONN_UPDATE_EVT);
    ble_at_mode_init();
    rf_phy_set_txPower(power_table[user_data.power]);
    g_rfPhyTxPower = power_table[user_data.power];
    at_data.ble_send_index = 0xff;
    at_data.ble_send_role = 0xff;
    
    at_data.data_type = AT_UART;
    at_data.at_cmd_flag = 0;

    if(user_data.autolink != 0)
    {
        ble_task_set(USER_TASK_START, START_MASTER_CONN_EVT, NULL);
        for(int i = 0 ; i < g_slaveMaxNum ; i++)
        {
            slaveDevInfo[i].AutoConnection = (user_data.autolink>>i)&0x01;
            
            if(slaveDevInfo[i].AutoConnection == 1)
            {
                LOG("flash mac:");
                LOG_DUMP_BYTE(slaveDevInfo[i].PeerAddr,6);
                osal_memcpy(slaveDevInfo[i].PeerAddr,&user_data.autolinkaddr[i][0],B_ADDR_LEN);
                at_white_list_enable(i,1);

            }
            
            LOG("slaveDevInfo[%d].AutoConnection %d\n",i,slaveDevInfo[i].AutoConnection);
        }
    }
}
/**
 * @brief user_data_init
 * 
 */
void  user_data_init(void)
{
	uint8	buf[6];
	uint32	addr = 0;
	uint32	index1 = 0;
	uint32	index2 = 0;
	
	osal_memset(buf, 0, 6);
	osal_memset((uint8*)&user_data, 0, sizeof(hal_uart_data_t));
	
	HalFlashRead(BAUD_FLASH_ADDR1, buf, 6);
	if( (buf[0] == 0xAA) && (buf[1] == 0x55) )
	{
		index1 = (buf[5]<<24) | (buf[4]<<16) | (buf[3]<<8) | buf[2];
	}
	
	osal_memset(buf, 0, 6);
	HalFlashRead(BAUD_FLASH_ADDR2, buf, 6);
	if( (buf[0] == 0xAA) && (buf[1] == 0x55) )
	{
		index2 = (buf[5]<<24) | (buf[4]<<16) | (buf[3]<<8) | buf[2];
	}
	
	if(index1 > index2)
	{
		bank_curr_num = 0;
		addr = BAUD_FLASH_ADDR1;
	}
	else if(index2 > index1)
	{
		bank_curr_num = 1;
		addr = BAUD_FLASH_ADDR2;
	}
	else
	{
        osal_memset((uint8*)&user_data, 0, sizeof(hal_uart_data_t));
	}

	if(addr)
	{
		HalFlashRead(addr, (uint8*)&user_data, sizeof(hal_uart_data_t));
		if( user_data_sum(sizeof(user_data)-1, (uint8*)&user_data) != user_data.check_sum )
		{
			osal_memset((uint8*)&user_data, 0, sizeof(hal_uart_data_t));
		}
	}

    if(user_data.flg != 0x55AA)
    {
        user_data.flg = 0x55AA;
        user_data.index = 1;
        user_data.blemode = BLE_ONLY_SLAVE;
        user_data.autolink = 0;
        user_data.service.flag = 0xff;
        user_data.scan_interval = 1;//ms
        user_data.scan_window = 3;//ms
        user_data.power = 3;
        user_data.service.flag = 0;

		user_data.service.main_service[1] = bleuart_ServiceUUID[0];
		user_data.service.main_service[0] = bleuart_ServiceUUID[1];

		user_data.service.notify[1] = bleuart_TxCharUUID[0];
		user_data.service.notify[0] = bleuart_TxCharUUID[1];

		user_data.service.wr[1] = bleuart_RxCharUUID[0];
		user_data.service.wr[0] = bleuart_RxCharUUID[1];

		user_data.service.at[1] = bleuart_AT_UUID[0];
		user_data.service.at[0] = bleuart_AT_UUID[1];

		user_data.service.main_service[1] = blemulti_ServiceUUID[0];
		user_data.service.main_service[0] = blemulti_ServiceUUID[1];

		user_data.service.notify[1] = blemulti_TxCharUUID[0];
		user_data.service.notify[0] = blemulti_TxCharUUID[1];

		user_data.service.wr[1] = blemulti_RxCharUUID[0];
		user_data.service.wr[0] = blemulti_RxCharUUID[1];
        HalFlashRead(0x1000, (uint8*)&user_data.mac, sizeof(user_data.mac));
        osal_memcpy(user_data.name, DEVICE_NAME, ((osal_strlen((char *)DEVICE_NAME)>25)?25:osal_strlen((char *)DEVICE_NAME)));
        user_data_save();
    }
    //user_at_init();
    //ble_service_init();scan_window_table
    LOG("win:%d\r\n", scan_window_table[user_data.scan_window]);
    LOG("inter:%d\r\n", scan_interval_table[user_data.scan_interval]);
    LOG("baud:%d\r\n", baud_table[user_data.baud]);
    LOG("advin:%d\r\n", advin_table[user_data.advin]);
    LOG("connin:%d\r\n", connin_table[user_data.connin]);
    LOG("power:%d\r\n", user_data.power);
    LOG("name:%s\r\n", user_data.name);
    LOG("blemode:%d\r\n", user_data.blemode);
    LOG("mac:%02X%02X%02X%02X%02X%02X\r\n", user_data.mac[5], \
                                            user_data.mac[4], \
                                            user_data.mac[3], \
                                            user_data.mac[2], \
                                            user_data.mac[1], \
                                            user_data.mac[0]);
}

/**
 * @brief user_data_save
 * 
 */
void user_data_save(void)
{
	uint32 addr = 0;
	
	bank_curr_num = !bank_curr_num;
	
	user_data.flg = 0x55AA;
	user_data.index++;
	user_data.check_sum = user_data_sum(sizeof(user_data)-1, (uint8*)&user_data);
	if(bank_curr_num)
	{
		addr = BAUD_FLASH_ADDR2;
	}
	else
	{
		addr = BAUD_FLASH_ADDR1;
	}
	//LOG("user_data.check_sum %d\n",user_data.check_sum);
	HalFlashErase(addr>>12);
	HalFlashWrite(addr, (uint8*)&user_data, sizeof(user_data));
}


/**
 * @fn      void HalPeripheral_Init(uint8 task_id)
 * @brief   Peripheral initialization
 * @param   task_id
 * @return  none
 */
void HalPeripheral_Init(uint8 task_id)
{
    Hal_UartTaskID = task_id;

    user_data_init();

    HalGpioPinInit(WAKEUP_PIN, GPIO_INPUT);
    HalGpioPupdConfig(WAKEUP_PIN, GPIO_PULL_UP);
    HalGpioWkupConfig(WAKEUP_PIN, POL_FALLING);
    HalGpioRegister(WAKEUP_PIN, wakeup_pin_hdl, wakeup_pin_hdl);//注册按键唤醒回调
    
    HalGpioPinInit(BT_STATUS_PIN, GPIO_OUTPUT);
    HalGpioSet(BT_STATUS_PIN, Bit_DISABLE);
    
    uart_Cfg_t cfg = {
        .tx_pin = P20,
        .rx_pin = P18,
        .baudrate = baud_table[user_data.baud],
        .use_fifo = TRUE,
        .hw_fwctrl = FALSE,
        .use_tx_buf = FALSE,//TRUE,//关闭中断发送串口数据
        .parity     = FALSE,
        .evt_handler = uart_receive_callback,
    };
    HalUartInit(UART1, cfg);//uart init
    HalUartSetTxBuf(UART1, uart_send_buff, UART_BUF_SIZE);

    //osal_memcpy(uart_send_buf, "OK\r\n", 4);
    HalUartSendBuf(UART1, "OK\r\n", 4);
    
    osal_start_timerEx(Hal_UartTaskID, USR_WAKEUP_PIN_DET, PIN_DEBONCE_TIME);
}


